﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using System.Windows.Forms;
using System.Xml;
using System.IO;
using MyLog;

namespace Notification {
    internal static class Program {
        /// <summary>
        ///     检测网络状态的WINAPI
        /// </summary>
        /// <param name="connectionDescription"></param>
        /// <param name="reservedValue"></param>
        /// <returns></returns>
        [DllImport("wininet.dll")]
        private static extern bool InternetGetConnectedState(out int connectionDescription, int reservedValue);
        private static ApplicationContext _applicationContext;
        public static int CurrentUserId = 34;
        public static string CurrentUserName = "测试账号";
        public static UpdateInfo UpdateInfo;
        public static bool IsUpdate = false;

        /// <summary>
        ///     应用程序的主入口点。
        /// </summary>
        [STAThread]
        private static void Main(string[] args) {
            LogHelper.WriteLog("程序正常启动...");

            // 绑定程序中的异常处理
            BindExceptionHandler();

            // 初始化传入的参数
            InitParameter(args);
            // 保证单例
            KeepSingle();

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            var path = Application.StartupPath;
            if (path.EndsWith("Update", StringComparison.OrdinalIgnoreCase)) {
                var sourceFileName = path + "\\Notification.exe";
                var pos = path.LastIndexOf("\\", StringComparison.Ordinal);
                var targetFileName = path.Substring(0, pos) + "\\Notification.exe";
                File.Copy(sourceFileName, targetFileName, true);
            }

            var frmFlash = new FrmFlash();
            frmFlash.Show();
            _applicationContext = new ApplicationContext();
            _applicationContext.Tag = frmFlash;
            Application.Idle += Application_Idle;

            Application.Run(_applicationContext);
        }

        private static void BindExceptionHandler() {
            //设置应用程序处理异常方式：ThreadException处理
            Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
            //处理UI线程异常
            Application.ThreadException += Application_ThreadException;
            //处理未捕获的异常
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
        }

        /// <summary>
        ///     处理UI线程异常
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) {
            LogHelper.WriteLog("UI线程异常", e.Exception);
        }

        /// <summary>
        ///     处理未捕获的异常
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
            LogHelper.WriteLog("未捕获的异常", e.ExceptionObject as Exception);
        }

        private static void Application_Idle(object sender, EventArgs e) {
            Application.Idle -= Application_Idle;
            CheckUpdate();
            if (_applicationContext.MainForm == null && !IsUpdate) {
                var frmMain = new FrmMain();
                _applicationContext.MainForm = frmMain;
                ((FrmFlash)(_applicationContext.Tag)).Close();
                frmMain.Show();
            }
        }

        private static void CheckUpdate() {
            int connectionDescription;
            // 检测网络连接的状态
            if (!InternetGetConnectedState(out connectionDescription, 0)) {
                MessageBox.Show(@"网络连接异常，无法及时的检测系统是否需要更新，请检查计算机的网络连接设置。", @"更新提示", MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
            } else {
                // 获取远程更新的配置文件信息
                GetUpdateInfo();

                var localVersion = new Version(Application.ProductVersion);
                var remoteVersion = new Version(Program.UpdateInfo.ReleaseVersion);
                LogHelper.WriteLog("本地版本：" + localVersion);
                LogHelper.WriteLog("远程版本：" + remoteVersion);

                if (localVersion.CompareTo(remoteVersion) < 0) {
                    LogHelper.WriteLog("升级当前的程序");
                    MessageBox.Show(@"发现新版本程序，需要更新。", @"更新提示", MessageBoxButtons.OK, MessageBoxIcon.Question);
                    IsUpdate = true;
                    new FrmAutoUpdater().Show();
                }
            }
        }

        private static void InitParameter(string[] args) {
            if (args != null && args.Length > 0) {
                LogHelper.WriteLog("参数长度：" + args.Length);
                for (var i = 0; i < args.Length; i++) {
                    LogHelper.WriteLog(string.Format("参数{0}：{1}", i + 1, args[i]));
                }
                const string pattern = @"(?<=://).+?(?=:|/|\Z)";
                var parameters = Regex.Match(args[0], pattern).Value.Split(',');
                CurrentUserId = Convert.ToInt32(parameters[0]);
                // 转码（URL编码转换成UTF-8）
                CurrentUserName = HttpUtility.UrlDecode(parameters[1], Encoding.UTF8);
            }

            LogHelper.WriteLog("登录用户Id：" + CurrentUserId);
            LogHelper.WriteLog("登录用户姓名：" + CurrentUserName);
        }

        private static void KeepSingle() {
            var current = Process.GetCurrentProcess();
            var processes = Process.GetProcessesByName(current.ProcessName);
            foreach (var process in processes) {
                if (process.Id == current.Id) {
                    continue;
                }
                if (Assembly.GetExecutingAssembly().Location.Replace("/", "\\") == current.MainModule.FileName) {
                    process.Kill();
                }
            }
        }

        /// <summary>
        ///     获取远程的更新配置文件
        /// </summary>
        /// <returns></returns>
        private static void GetUpdateInfo() {
            try {
                var tmpWebClient = new WebClient();
                var stream = tmpWebClient.OpenRead(ConfigurationManager.AppSettings["updateInfo"]);
                var doc = new XmlDocument();
                if (stream != null) {
                    doc.Load(stream);
                    Program.UpdateInfo = new UpdateInfo();
                    var root = doc.DocumentElement;
                    if (root != null) {
                        Program.UpdateInfo.AppName = root.ChildNodes[0].InnerText;
                        Program.UpdateInfo.ReleaseUrl = root.ChildNodes[1].InnerText;
                        Program.UpdateInfo.ReleaseVersion = root.ChildNodes[2].InnerText;
                        Program.UpdateInfo.UpdateDescription = root.ChildNodes[3].InnerText;
                        Program.UpdateInfo.DownloadFiles = new List<string>();
                        foreach (var node in root.ChildNodes[4].ChildNodes) {
                            if (node is XmlElement) {
                                Program.UpdateInfo.DownloadFiles.Add((node as XmlElement).Attributes["name"].Value);
                            }
                        }
                    }
                }
                tmpWebClient.Dispose();
            } catch {

            }
        }
    }
}